/**
 * @description:
 * @file: methods.ts
 * @author: Evan
 * @date: 2025.06.06 14:01:49
 * @week: 周五
 * @version: V
 */

import * as ECHARTS from 'echarts/core'
import { formatDate, stringToDate } from '@/utils/date'
import i18n from '@/locales'
const { t } = i18n.global

/**
 * 获取渐变色
 * @param colors 颜色列表 长度 2
 * @param x 控制渐变色的起始x 坐标方向
 * @param y 控制渐变色的起始y 坐标方向
 * @param x2 控制渐变色的结束x 坐标方向
 * @param y2 控制渐变色的结束y 坐标方向
 * @returns
 */
export const getLinearGradient = (colors: string[], x = 0, y = 0, x2 = 0, y2 = 1) => {
  return new ECHARTS.graphic.LinearGradient(x, y, x2, y2, [
    {
      offset: 0,
      color: colors[0]
    },
    {
      offset: 1,
      color: colors[1]
    }
  ])
}

/**
 *
 * @param type 时间间隔：hour/day/week/month/quarter/year
 * @returns
 */
export const getDateFormat = (type: string) => {
  if (type == 'hour') return 'yyyy-MM-dd hh:mm'
  else if (type == 'week') return 'yyyy-第ww周'
  else if (type == 'quarter') return 'yyyy-第qq季度'
  else if (type == 'month') return 'yyyy-MM'
  else if (type == 'year') return 'yyyy'
  return 'yyyy-MM-dd'
}

/**
 * 格式化数据源
 * @param opts 配置
 * @returns
 */
export const formatDataSource = (opts: {
  /**
   * 列表
   */
  list: AnyObject[]
  /**
   * 时间戳-字段名
   */
  tsKey?: string
  /**
   * 值-字段名
   */
  valKey?: string
  /**
   * 格式 如：yyyy-MM-dd
   */
  ftm?: string
  /**
   * 类型轴 后缀名称
   * 如：时间传入的是月份数字，后缀需要加 '月' 则传
   */
  suffix?: string
  /**
   * table 表格横向统计 - 图表一条线对应一条数据
   */
  horizontal?: boolean
}) => {
  const { list, tsKey = 'timeStamp', valKey = 'data', suffix = '', ftm, horizontal } = opts
  // 数据源格式
  const source: (string | number)[][] = [['product']]
  // series 数据格式
  const series: { name: string; data: number[] }[] = []
  const labels: string[] = []
  // table 数据格式
  const table: { name: string; [key: string]: number | string }[] = []

  // 查找最长数组下标
  let index = 0
  for (let i = 0; i < list.length; i++) {
    if (i > 0 && list[i].list.length > list[i - 1].list.length) {
      index = i
    }
  }

  for (let i = 0; i < list.length; i++) {
    const item = list[i]
    const data = item.list || []
    const label = String(item.name)
    source[0].push(label)

    series.push({
      name: label,
      data: []
    })

    // 横向统计
    if (horizontal) {
      table.push({
        name: label
      })
    }

    let total = 0
    // 循环二级
    for (let j = 0; j < data.length; j++) {
      const _item = data[j]
      // 默认为时间戳
      let tsp = Number(_item[tsKey])
      if (isNaN(tsp)) {
        tsp = stringToDate(String(_item[tsKey])).getTime()
      }

      // 判断时间戳是否大于 1e12 格式化，否则输出原数据
      const name = tsp > 1e12 ? formatDate(tsp, ftm) : String(tsp) + suffix

      const value = data[j][valKey]
      if (source[j + 1]) {
        source[j + 1][i + 1] = value
      } else {
        // 第一条数据
        if (i == 0) {
          source[j + 1] = [name, value]
        } else {
          // 补足长度后天津的当前数据
          source[j + 1] = [name].concat(new Array(i).fill(0).concat(value))
        }
      }
      // 记录最长数组日期
      if (i == index) {
        labels.push(name)
      }
      series[i].data[j] = value

      // 默认纵向统计
      if (!horizontal) {
        if (!table[j]) {
          table.push({
            name: label
          })
        }
        table[j][`tsKey` + (i + 1)] = name
        table[j][`valKey` + (i + 1)] = value
      } else {
        total += value
        table[i][`tsKey` + (j + 1)] = name
        table[i][`valKey` + (j + 1)] = value
      }
    }

    // 横向统计
    if (horizontal) {
      table[i].total = total
    }
  }
  return {
    source,
    series,
    table,
    labels
  }
}

/**
 * 获取 图表中 x 轴时间轴的基础值
 * @param timeStamp 时间戳
 * @param timeInterval 时间类型 如：hour/day/week/month/quarter/year
 * @returns {string}
 *  getXAxisTimeBase('1745683200000', 'hour') //2025-04-27 00:00:00.000
 */
export const getXAxisTimeBase = (timeStamp: string | number, timeInterval: string) => {
  let tsp = Number(timeStamp)
  if (isNaN(tsp)) {
    tsp = stringToDate(String(timeStamp)).getTime()
  }
  let ftm = getDateFormat(timeInterval)
  // 判断时间戳是否大于 1e12 格式化，否则输出原数据
  const time = tsp > 1e12 ? formatDate(tsp, ftm) : String(tsp)
  return time
}

/**
 * 获取 图表中的数据
 * @param data 数据源
 * @param key 字段名
 * @returns {number[]}
 * *  mapData([
 *    {timeStamp: 1629907200000, data: 10},
 *    {timeStamp: 1629993600000, data: 20},
 *    {timeStamp: 1630080000000, data: 30}
 *  ], 'data') // [10, 20, 30]
 */
interface StatisticData {
  timeStamp: number
  data: number
}
export const mapData = (data: StatisticData[], key: keyof StatisticData): number[] => {
  return data?.map(item => item[key]) || []
}

/**
 * 转换数值
 * @param num 数值
 * @returns
 */
export const convertNum = (num: number) => {
  return t('fn.num', { value: num, precision: 2 })
}

/**
 * 获取列HTML文本
 * @param { Number } margin
 * @param { String } color
 * @param { String } label
 * @param { String } value
 * */
const tooltipFormatterRowHTML = (
  margin: number,
  color: string,
  label: string,
  value: string,
  isSub = false
) => {
  return `
    <div style="margin: ${margin / 14}em 0 0; line-height: 1">
      <div style="margin: 0px 0 0; line-height: 1">
        <span
          style="
            display: inline-block;
            margin-right: 0.3em;
            margin-left: ${isSub ? 0.2 : 0}em;
            border-radius: 50%;
            width: ${isSub ? 0.4 : 0.8}em;
            height: ${isSub ? 0.4 : 0.8}em;
            background-color: ${color};
          "
        ></span>
        <span style="font-size: ${isSub ? 0.8 : 1}em">${label}</span>
        <span
          style="
            float: right;
            margin-left: 0.75em;
            font-size: 1.2em;
            font-weight: 500;
            color: #fff
          "
          >${value}</span
        >
        <div style="clear: both"></div>
      </div>
      <div style="clear: both"></div>
    </div>
  `
}

/**
 * 获取公共提示
 * @param { Object | Array } params 格式化参数
 * @param { String | Array} unit 单位
 * @returns HTMLText
 * */
export const tooltipFormatter = (params: AnyObject, unit: string | string[] = '') => {
  // 判断单个还是列表
  params = params instanceof Array ? params : [params]

  let text = `
    <div style="margin: 0px 0 0; line-height: 1; border-color: red">
      <div style="margin: 0px 0 0; line-height: 1">
        <div
          style="font-size: 1.2em; font-weight: 400; line-height: 1"
        >
        ${params[0].name}
        </div>
        <div style="margin: 10px 0 0; line-height: 1">
  `
  for (let i = 0; i < params.length; i++) {
    let currObj = params[i]
    let color = currObj.color
    // 判断颜色是否为对象
    if (typeof color == 'object') {
      color = color.colorStops[0].color
    }
    const index = currObj.seriesIndex != void 0 ? currObj.seriesIndex : i
    const seriesType = currObj.seriesType

    // 判断单位是否为数组
    let _unit = unit
    if (unit instanceof Array) {
      // 长度等于 1 则使用相同
      if (unit.length == 1) {
        _unit = unit[0] || ''
      } else {
        _unit = unit[index] || ''
      }
    }

    let value = '0'
    if (currObj.value instanceof Array) {
      value = convertNum(currObj.value[currObj.encode.y[0]] || 0) as string
    } else {
      value = convertNum(currObj.value || 0) as string
    }

    const margin = i == 0 ? 0 : 10

    if (seriesType === 'candlestick') {
      const vals = currObj.value
      const indexs = currObj.encode.y
      text += tooltipFormatterRowHTML(margin, color, currObj.seriesName, ``)
      for (let i = 0; i < indexs.length; i++) {
        const j = indexs[i]
        const name = t(`message.candlestick_names[${i}]`)
        text += tooltipFormatterRowHTML(8, color, name, `${vals[j] || 0} ${_unit}`, true)
      }
    } else {
      text += tooltipFormatterRowHTML(margin, color, currObj.seriesName, `${value} ${_unit}`)
    }
  }
  text += `
        <div style="clear: both"></div>
        </div>
        <div style="clear: both"></div>
      </div>
      <div style="clear: both"></div>
    </div>
  `
  return text
}

/**
 * 创建表格 toolbox
 * @param { Object } opt 工具箱配置
 * @returns HTMLText
 * 暂时只支持xAxis[0].data和series数组的name和data属性
 */
export const createTabContent = (opt: AnyObject) => {
  const axisData = opt.xAxis[0].data || [] // 时间轴数据
  const series = opt.series || [] // 动态series数组
  let table = `
    <table style="width:100%;text-align:center" id="table-content">
      <tbody>
        <tr>
          <td>时间</td>
  `
  // 动态生成表头（遍历所有series）
  series.forEach((item: AnyObject) => {
    table += `<td>${item?.name || ''}</td>`
  })
  table += `</tr>`
  // 动态生成数据行（遍历所有时间点）
  for (let i = 0; i < axisData.length; i++) {
    table += `<tr><td>${axisData[i]}</td>`
    // 动态生成每行的数据列（遍历所有series）
    series.forEach((item: AnyObject) => {
      table += `<td>${item?.data?.[i] ?? ''}</td>`
    })
    table += `</tr>`
  }
  table += `</tbody></table>`
  return table
}
